﻿// Copyright (c) Vitaly Kamiansky. All rights reserved. 
// See License.txt in the project root.

using Property.Subscriptions;
using System;
using System.Linq;

namespace Property
{
    /// <summary>
    /// Contains words that can be applied to property instances. 
    /// </summary>
    public static class PropertyExtensionsChains
    {
        /// <summary>
        /// <para>Create a new PropertyChanging event subscription.</para>
        /// <para>( ! ) Don't forget to dispose of it.</para>
        /// </summary>
        /// <param name="action">Tell me what I should do
        /// when the event is raised.</param>
        public static IDisposable OnChanging<T>(this IProperty<T> source, Action action)
        {
            if (source == null) throw new ArgumentNullException("source");
            if (action == null) throw new ArgumentNullException("action");

            return new ChangingActionSubscription<T>(source, action);
        }

        /// <summary>
        /// <para>Create a new PropertyChanging event subscription.</para>
        /// <para>( ! ) Don't forget to dispose of it.</para>
        /// </summary>
        /// <param name="target">Tell me what object to call
        /// when the event is raised.</param>
        public static IDisposable OnChanging<T>(this IProperty<T> source, Func<ICallDriven> target)
        {
            return source.OnChanging(() =>
                new[] { target }.Where(o => o != null).Select(o => o())
                .Where(o => o != null).ToList().ForEach(o => o.Go()));
        }

        /// <summary>
        /// <para>Create a new PropertyChanging event subscription.</para>
        /// <para>( ! ) Don't forget to dispose of it.</para>
        /// </summary>
        /// <param name="targets">Tell me what objects to call
        /// when the event is raised.</param>
        public static IDisposable OnChanging<T>(this IProperty<T> source, params Func<ICallDriven>[] targets)
        {
            return source.OnChanging(() =>
                targets.Where(o => o != null).Select(o => o())
                .Where(o => o != null).ToList().ForEach(o => o.Go()));
        }

        /// <summary>
        /// <para>Create a new PropertyChanged event subscription.</para>
        /// <para>( ! ) Don't forget to dispose of it.</para>
        /// </summary>
        /// <param name="action">Tell me what I should do
        /// when the event is raised.</param>
        public static IDisposable OnChanged<T>(this IProperty<T> source, Action action)
        {
            if (source == null) throw new ArgumentNullException("source");
            if (action == null) throw new ArgumentNullException("action");

            return new ChangedActionSubscription<T>(source, action);
        }

        /// <summary>
        /// <para>Create a new PropertyChanged event subscription.</para>
        /// <para>( ! ) Don't forget to dispose of it.</para>
        /// </summary>
        /// <param name="target">Tell me what object to call
        /// when the event is raised.</param>
        public static IDisposable OnChanged<T>(this IProperty<T> source, Func<ICallDriven> target)
        {
            return source.OnChanged(() =>
                new[] { target }.Where(o => o != null).Select(o => o())
                .Where(o => o != null).ToList().ForEach(o => o.Go()));
        }

        /// <summary>
        /// <para>Create a new PropertyChanged event subscription.</para>
        /// <para>( ! ) Don't forget to dispose of it.</para>
        /// </summary>
        /// <param name="targets">Tell me what objects to call
        /// when the event is raised.</param>
        public static IDisposable OnChanged<T>(this IProperty<T> source, params Func<ICallDriven>[] targets)
        {
            return source.OnChanged(() =>
                targets.Where(o => o != null).Select(o => o())
                .Where(o => o != null).ToList().ForEach(o => o.Go()));
        }
    }
}
